// ==================================================================================
// Shared Genomics Project MPI Codebase
// Version 1.0 30/04/2010
//
// (c) 2010 University of Manchester all rights reserved
//
// This file is distributed under the GNU General Public License, Version 2.  
// Please see the file COPYING.txt for more details
// ==================================================================================

/*!
\file
\brief Implementation of Random Seed File
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "copyfile.h"
#include "pmaths.h"
#include "seedfile.h"
#include "suffixes.h"
#include "utils.h"

int* seedfile_load(struct selected_options *ops, int *nSeeds) {
	int n = 0;
	int* seeds = NULL;
	char filepath[FILE_PATH_LENGTH];
	FILE *in = NULL;

	if (ops == NULL || nSeeds == NULL) {
		*nSeeds = 0;
		return seeds;
	}
	sprintf(filepath, "%s%s%s", ops->rdir, ops->szRunId, SUFFIX_RSEED_FILE);
	in = fopen(filepath, "rb");
	if (in == NULL) {
		*nSeeds = 0;
		return seeds;
	} else {
		// Read the declared number of processors.
		if (fread(&n, sizeof(int), 1, in) != 1) {
			fclose(in);
			*nSeeds = 0;
			return seeds;
		} else *nSeeds = n;
		
		// File has zero 'seed' values, that may be a problem.
		if (n < 1) {
			*nSeeds = 0;
		} else {
			// Allocate memory for the 'seed' buffer.
			seeds = (int*) malloc(n * sizeof(int));
			if (seeds != NULL) {
				if (fread(seeds, sizeof(int) * n, 1, in) != 1) {
					// If here, the I/O read failed.
					free(seeds);
					seeds = NULL;
					*nSeeds = 0;
				}
			}
		}

		fclose(in);
	}

	return seeds;
}

int seedfile_create(struct selected_options *ops, int numprocs) {
	FILE *out = NULL;
	int now = (int) time(NULL);

	if (ops == NULL || numprocs < 0) return 0;
	else if (now <= 0 || strlen(ops->szSeedFileName) == 0) return 0;
	
	out = fopen(ops->szSeedFileName, "wb");
	if (out == NULL) return -1;
	else {
		int i;

		// No. random seeds in file.
		if (fwrite(&numprocs, sizeof(int), 1, out) != 1) {
			if (out != NULL) fclose(out);
			return 0;
		}

		// The random seeds
		for (i = 0; i < numprocs; i++) {
			int value = get_rand(now);
			if (fwrite(&value, sizeof(int), 1, out) != 1) {
				if (out != NULL) fclose(out);
				return 0;
			}
		}
		fclose(out);
	}

	return 1;
}

int seedfile_create_and_copy(struct selected_options *ops, int numprocs, int rank) {
	BOOL jobDone = FALSE;
	char tmp_szRunId[TOKEN_LENGTH], remoteFilepath[FILE_PATH_LENGTH];

	if (ops == NULL) return 0;

	strcpy(tmp_szRunId, ops->szRunId);
	sprintf(ops->szRunId, "%s_%i", tmp_szRunId, rank);

	sprintf(ops->szSeedFileName, "%s%s%s_%i", ops->ldir, ops->szRunId, SUFFIX_RSEED_FILE, rank);
	sprintf(remoteFilepath, "%s%s%s", ops->rdir, tmp_szRunId, SUFFIX_RSEED_FILE);

	if (seedfile_create(ops, numprocs))  if (copyAndDeleteFile(ops->szSeedFileName, remoteFilepath)) jobDone = TRUE;
	
	strcpy(ops->szRunId, tmp_szRunId); // Restore the original Run ID

	if (jobDone) return 1;
	else return 0;
}

// SUFFIX_SEED_LOG_FILE
int rseed_log(struct selected_options *ops, unsigned long seed) {
	FILE *out = NULL;
	char localFilepath[FILE_PATH_LENGTH], remoteFilepath[FILE_PATH_LENGTH];
	BOOL jobDone = FALSE;

	if (ops == NULL) return 0;

	sprintf(localFilepath, "%s%s%s", ops->ldir, ops->szRunId, SUFFIX_RSEED_LOG_FILE);
	sprintf(remoteFilepath, "%s%s%s", ops->rdir, ops->szRunId, SUFFIX_RSEED_LOG_FILE);

	out = fopen(localFilepath, "w");
	if (out != NULL) {
		fprintf(out, "%u\n", seed);
		fclose(out);
		if (copyAndDeleteFile(localFilepath, remoteFilepath)) jobDone = TRUE;
	}

	if (jobDone) return 1;
	else return 0;
}